/* Some Taken from the Corchero's Examples */

#include <iostream>


#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#include "GLSL.hh"

#define MAXLINEA 255
#define SHADERS_DIR ""



#define glXGetProcAddress(x) (*glXGetProcAddressARB)((const GLubyte*)x)
PFNGLCREATEPROGRAMOBJECTARBPROC     glCreateProgramObjectARB = NULL;
PFNGLCREATESHADEROBJECTARBPROC      glCreateShaderObjectARB = NULL;
PFNGLSHADERSOURCEARBPROC            glShaderSourceARB = NULL;
PFNGLCOMPILESHADERARBPROC           glCompileShaderARB = NULL;
PFNGLGETOBJECTPARAMETERIVARBPROC    glGetObjectParameterivARB = NULL;
PFNGLATTACHOBJECTARBPROC            glAttachObjectARB = NULL;
PFNGLGETINFOLOGARBPROC              glGetInfoLogARB = NULL;
PFNGLLINKPROGRAMARBPROC             glLinkProgramARB = NULL;
PFNGLUSEPROGRAMOBJECTARBPROC        glUseProgramObjectARB = NULL;
PFNGLGETUNIFORMLOCATIONARBPROC      glGetUniformLocationARB = NULL;
PFNGLUNIFORM1FARBPROC               glUniform1f = NULL;

int SetupGLSL(){
  glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) glXGetProcAddress("glCreateProgramObjectARB");
  glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) glXGetProcAddress("glCreateShaderObjectARB");
  glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) glXGetProcAddress("glShaderSourceARB");
  glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) glXGetProcAddress("glCompileShaderARB");
  glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) glXGetProcAddress("glGetObjectParameterivARB");
  glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) glXGetProcAddress("glAttachObjectARB");
  glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) glXGetProcAddress("glGetInfoLogARB");
  glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) glXGetProcAddress("glLinkProgramARB");
  glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) glXGetProcAddress("glUseProgramObjectARB");
  glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) glXGetProcAddress("glGetUniformLocationARB");
  glUniform1f = (PFNGLUNIFORM1FARBPROC) glXGetProcAddress("glUniform1fARB");
  
  glewInit();
  if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)  
    return 0;
  
  return -1;

}


char *textFileRead(char *fn) {
  FILE *fp; int f,count; char *content = NULL;
  
  f = open(fn, O_RDONLY);
  count = lseek(f, 0, SEEK_END);
  close(f);
  
  if (fn != NULL) {
    fp = fopen(fn,"rt");
    if (fp != NULL) {
      if (count > 0) {
	content = (char *)malloc(sizeof(char) * (count+1));
	count = fread(content,sizeof(char),count,fp);
	content[count] = '\0';
      }
      fclose(fp);
    }
  }
  return content;
}   


// Ojo ... strcpy ... cambiar ASAP!!
GLhandleARB SetShader(const char *path) {
  char *vs,*fs,vs_ruta[MAXLINEA],fs_ruta[MAXLINEA],rutacpy[MAXLINEA];
  GLhandleARB v,f,p;
  
  v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
  f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
  
  strcpy(rutacpy,SHADERS_DIR);
  strcat(rutacpy,path);
  
  strcpy(vs_ruta,rutacpy);
  strcat(vs_ruta,".vert");
  
  strcpy(fs_ruta,rutacpy);
  strcat(fs_ruta,".frag");
  
  vs = textFileRead(vs_ruta);
  fs = textFileRead(fs_ruta);
  
  const char * ff = fs;
  const char * vv = vs;
  
  glShaderSourceARB(v, 1, &vv,NULL);
  glShaderSourceARB(f, 1, &ff,NULL);
  
  free(vs);free(fs);
  
  glCompileShaderARB(v);
  glCompileShaderARB(f);
  
  p = glCreateProgramObjectARB();
  
  glAttachObjectARB(p,f);
  glAttachObjectARB(p,v);
  
  glLinkProgramARB(p);
  
  return p;
}


GLhandleARB SetShader_(const char* ff, const char* vv) {

  GLhandleARB v,f,p;
  
  v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
  f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
  
  glShaderSourceARB(v, 1, &vv,NULL);
  glShaderSourceARB(f, 1, &ff,NULL);
  
   
  glCompileShaderARB(v);
  glCompileShaderARB(f);
  
  p = glCreateProgramObjectARB();
  
  glAttachObjectARB(p,f);
  glAttachObjectARB(p,v);
  
  glLinkProgramARB(p);
  
  return p;
}
